package com.autumn.platform.core.context.track.impl;

import org.springframework.core.NamedInheritableThreadLocal;

import com.autumn.platform.core.Utils;
import com.autumn.platform.core.context.track.ITracker;
import com.autumn.platform.core.logger.Logs;

public abstract class AbstractThreadLocalTracker implements ITracker {

    private static final ThreadLocal<String> trackIdLocal = new NamedInheritableThreadLocal<String>("tracker");

    /**
     * 生成跟踪号
     * 
     * @return 跟踪号
     */
    abstract protected String generateTrackId();

    /**
     * 开始跟踪
     */
    @Override
    public void start() {
        String id = trackIdLocal.get();
        if (!Utils.isBlank(id)) {
            Logs.debug("the tracker has started, the trackId is " + id + ".");
        } else {
            this.startNewTracker();
        }
    }

    /**
     * 开始新的跟踪
     */
    private void startNewTracker() {
        trackIdLocal.set(generateTrackId());
    }

    /**
     * 使用指定跟踪号开始新的跟踪
     */
    @Override
    public void start(String trackId) {
        String id = trackIdLocal.get();
        if (!Utils.isBlank(id)) {
            Logs.debug("the old trackId is " + id + ", and override using new trackId " + trackId + ".");
        }
        trackIdLocal.set(trackId);
    }

    /**
     * 判断是否正在跟踪
     */
    @Override
    public boolean isTracking() {
        return !Utils.isBlank(trackIdLocal.get());
    }

    /**
     * 获取目前的跟踪号
     */
    @Override
    public String getCurrentTrackId() {
        return trackIdLocal.get();
    }

    @Override
    public String appendTrackId(String src) {
        String trackId = getCurrentTrackId();
        if (null != trackId) {
            if (null == src) {
                src = "[trackId: " + trackId + "] ";
            } else if (src.indexOf(trackId) == -1) {
                src = "[trackId: " + trackId + "] " + src;
            }
        }
        return src;
    }

    /**
     * 停止跟踪
     */
    @Override
    public void stop() {
        trackIdLocal.remove();
    }
}
